function gewFloatMap(url,mipmapLevelNum,queryItem)
{
  this.width = 0;
  this.height = 0;
  this.data = [];
  this.url = url;
  this.isReady = false;
  this.mipmapLevel = mipmapLevelNum;
  var xhr = new XMLHttpRequest();
  xhr.gewFloatMap = this;
  xhr.onreadystatechange = function() 
  {
    if(xhr.readyState == 4) 
    {
      if (xhr.status == 200 || xhr.status == 0) 
      {        
        queryItem.status = GEW_DOWNLOAD_STATUS_FINISHED;
        xhr.gewFloatMap.parseData(xhr.responseText);
      }
      else 
      {
          alert("gewFloatMap::Error when load "+url+"!");  
      }        
    }
  }
  xhr.open("GET", url, true);
  xhr.overrideMimeType("text/plain; charset=x-user-defined");
  xhr.setRequestHeader("Content-Type", "text/plain");
  queryItem.xhr = xhr;
}
gewFloatMap.prototype.parseData = function(data)
{
  if( data[0]!=' '||data[1]!=' '||data[2]!='f'||data[3]!='m')
  {
    alert("gewFloatMap:parseData::This file isn't a float map");
  }
  var offset = 4;
  var w = gewReadUInt32(data, offset);
  this.width = w;
  offset += 4;
  var h = gewReadUInt32(data, offset);
  this.height = h;
  offset += 4;
  var minHeight = gewReadFixed(data, offset,GEW_FIXED_POINT_32);
  offset += 4;
  var maxHeight = gewReadFixed(data, offset,GEW_FIXED_POINT_32);
  offset += 4;
  this.data[0] = new WebGLFloatArray(w*h);
  //this.data = [];
  var buf = this.data[0];
  var factor =0;
  for(var i=0;i<w*h;i++)
  {
    factor  = gewReadUInt16(data,offset)/65536.0;
    buf[i] = minHeight*(1.-factor)+maxHeight*factor;
    offset+=2;          
  }
  if(this.mipmapLevel)
    this.generateMipmap(this.mipmapLevel);
  this.isReady = true;
}
// Height map utilities function
gewFloatMap.prototype.get = function(x,y) 
{
  var w= this.width;
  var h=  this.height;
  
  var col = w/2+ Math.round(x);
  var row = h/2+ Math.round(y);
  if(col<0)
  {
    var f = Math.ceil( Math.abs(col)/w);
    col = w*f+col;
  }
  if(col>=w)
  {
    var f = Math.ceil(col/w);
    col = w*f-col;
  }
  if(row<0)
  {
    var f = Math.ceil( Math.abs(row)/h);
    row = h*f+row;
  }
  if(row>=h)
  {
    var f = Math.ceil(row/h);
    row = h*f-row;
  } 
  return this.data[0][ col+ row*w];
}
gewFloatMap.prototype.getNormalAt = function(x,y,result)
{
  var xS = Math.floor(x);
  var zS = Math.floor(y);
  var fracX = x- xS;
  var fracZ = y- zS;    
  var h1 = this.get(xS,zS+1);
  var h2 = this.get(xS+1,zS);
  gewRegVec0.set(xS,h1,zS+1);
  gewRegVec1.set(xS+1,h2,zS);
  if(fracX+fracZ < 1)
  {
    var h3 = this.get(xS,zS);
    gewRegVec2.set(xS,h3,zS);
  }
  else
  {
    var h3 = this.get(xS+1,zS+1); 
    gewRegVec2.set(xS+1,h3,zS+1);
  }  
  var plane = new gewPlane( gewRegVec0,gewRegVec1,gewRegVec2);
  if(plane.b>0.0)
  {
    var x=plane.a;var y=plane.b;var z=plane.c;
  }
  else
  {
    var x=-plane.a;var y=-plane.b;var z=-plane.c;
  }
  if(!result)
    result = new gewVec3(x,y,z);
  else
    result.set(x,y,z);
  return result;
}
gewFloatMap.prototype.interpolationAt = function(x,y) 
{
  var xS = Math.floor(x);
  var zS = Math.floor(y);
  var fracX = x- xS;
  var fracZ = y- zS;
  
  if( (fracX< 0.05|| fracX>0.95)&&
      (fracZ< 0.05|| fracZ>0.95))
      return this.get(x,y);
    
  var h1 = this.get(xS,zS+1);
  var h2 = this.get(xS+1,zS);
  gewRegVec0.set(xS,h1,zS+1);
  gewRegVec1.set(xS+1,h2,zS);
  if(fracX+fracZ < 1)
  {
    var h3 = this.get(xS,zS);
    gewRegVec2.set(xS,h3,zS);
  }
  else
  {
    var h3 = this.get(xS+1,zS+1); 
    gewRegVec2.set(xS+1,h3,zS+1);
  }  
  var plane = new gewPlane( gewRegVec0,gewRegVec1,gewRegVec2);
  var height = -(plane.a*x+plane.c*y+plane.d)/plane.b;
  return height;    
}
gewFloatMap.prototype.generateMipmap = function(levelNum)
{
  var w = this.width;
  var h = this.height;
  for(var i=1;i<levelNum;i++)
  {
    w/=2;
    h/=2;
    var sample_num = w*h;
    this.data[i] = new WebGLFloatArray(sample_num);
    var cur_map = this.data[i];
    var finer_map = this.data[i-1];
    var sampler_per_row = w*4; // finer_map 
    for(var row = 0;row<h;row++)
    {
      for(var col = 0;col<w;col++)
      {
        var offset = row*sampler_per_row+ col*2
        cur_map[col+row*w] = ( finer_map[offset]+finer_map[offset+1]+finer_map[offset+w*2]+finer_map[offset+w*2+1])/4;
      }
    }
  }
}